/**
 * huize Service Inc
 * All Rights Reserved @2018
 */
package com.huize.ladon.apm.common.util;

/**
 * 描述: Byte字节码工具类,从"com.huize.framework.catfish.common.util.ByteUtil"移植过来, 避免apm-common与catfish-common工程相呼依赖
 *
 * @author tianyuliang
 * @version $Id: ByteUtils.java, v0.1 2019/4/3
 */
public final class ByteUtils {

    private ByteUtils() {
        // never instance
    }

    /**
     * 单字节转int
     *
     * @param b
     * @return
     */
    public static int byteToInt(byte b) {
        return (int) b & 0xFF;
    }

    /**
     * int转单字节
     *
     * @param i
     * @return
     */
    public static byte intToByte(int i) {
        return (byte) (i & 0xFF);
    }

    /**
     * short转化为byte数组,高字节在前
     *
     * @param i
     * @return
     */
    public static byte[] shortToBytes(short i) {
        byte[] buf = new byte[2];
        buf[1] = (byte) i;
        i >>= 8;
        buf[0] = (byte) i;
        return buf;
    }

    /**
     * byte数组转化为shor型,高字节在前
     *
     * @param buf
     * @return
     */
    public static short bytesToShort(byte[] buf) {
        short ret = 0;
        ret |= buf[0];
        ret <<= 8;
        ret |= buf[1] < 0 ? buf[1] + 256 : buf[1];
        return ret;
    }

    /**
     * int转字节数组(高字节序 : 高位在前)
     *
     * @param i
     * @param len --数组长度
     * @return
     */
    public static byte[] intToBytes(int i, int len) {
        if (len < 1 || len > 4) {
            return null;
        }

        byte[] buf = new byte[len];
        switch (len) {
            case 1:
                buf[0] = intToByte(i);
                break;
            case 2:
                buf[0] = (byte) ((i >> 8) & 0xFF);
                buf[1] = (byte) (i & 0xFF);
                break;
            case 3:
                buf[2] = (byte) i;
                i >>= 8;
                buf[1] = (byte) i;
                i >>= 8;
                buf[0] = (byte) i;
                break;
            case 4:
                buf[3] = (byte) i;
                i >>= 8;
                buf[2] = (byte) i;
                i >>= 8;
                buf[1] = (byte) i;
                i >>= 8;
                buf[0] = (byte) i;
                break;
        }
        return buf;
    }

    /**
     * 字节数组转int (高字节序 : 高位在前)
     *
     * @param buf
     * @return
     */
    public static int bytesToInt(byte[] buf) {
        if (null == buf) {
            return 0;
        }

        if (buf.length == 1) {
            return byteToInt(buf[0]);
        }

        int tmp = 0;
        int n = 0;
        for (int i = 0; i < buf.length; i++) {
            n <<= 8;
            tmp = buf[i] & 0xff;
            n |= tmp;
        }
        return n;
    }

    /**
     * byte[]转换为int (低字节序 : 低字节在前)
     *
     * @param buf
     * @return
     */
    public static int lBytesToInt(byte[] buf) {
        int s = 0;
        for (int i = 0; i < 3; i++) {
            if (buf[3 - i] >= 0) {
                s = s + buf[3 - i];
            } else {
                s = s + 256 + buf[3 - i];
            }
            s = s * 256;
        }
        if (buf[0] >= 0) {
            s = s + buf[0];
        } else {
            s = s + 256 + buf[0];
        }
        return s;

    }

    /**
     * 字节数组转long (高字节序 : 高位在前)
     *
     * @param buf
     * @return
     * @author hz15051315
     * @date 2019年3月7日 上午9:26:10
     * @version
     */
    public static long bytesToLong(byte[] buf) {
        long ret = 0;
        ret |= buf[0];
        ret <<= 8;
        ret |= buf[1] < 0 ? buf[1] + 256 : buf[1];
        ret <<= 8;
        ret |= buf[2] < 0 ? buf[2] + 256 : buf[2];
        ret <<= 8;
        ret |= buf[3] < 0 ? buf[3] + 256 : buf[3];
        ret <<= 8;
        ret |= buf[4] < 0 ? buf[4] + 256 : buf[4];
        ret <<= 8;
        ret |= buf[5] < 0 ? buf[5] + 256 : buf[5];
        ret <<= 8;
        ret |= buf[6] < 0 ? buf[6] + 256 : buf[6];
        ret <<= 8;
        ret |= buf[7] < 0 ? buf[7] + 256 : buf[7];
        return ret;
    }

    public static byte[] longToBytes(long i) {
        byte[] buf = new byte[8];
        buf[7] = (byte) i;
        i >>= 8;
        buf[6] = (byte) i;
        i >>= 8;
        buf[5] = (byte) i;
        i >>= 8;
        buf[4] = (byte) i;
        i >>= 8;
        buf[3] = (byte) i;
        i >>= 8;
        buf[2] = (byte) i;
        i >>= 8;
        buf[1] = (byte) i;
        i >>= 8;
        buf[0] = (byte) i;
        return buf;
    }

    /**
     * 计算冗余检验值 (异或)
     *
     * @param bytes
     * @param len
     * @return
     */
    public static int countXOR(byte[] bytes, int len) {
        int tmp = 0x00;
        for (int i = 0; i != len; i++) {
            tmp = tmp ^ byteToInt(bytes[i]);
        }
        return tmp;
    }

    /**
     * 计算数组中的数据累加和
     *
     * @param bytes
     * @return
     */
    public static int lcr(byte[] bytes) {
        if (null == bytes) {
            return 0;
        }

        int sum = 0;
        for (byte b : bytes) {
            sum += byteToInt(b);
        }
        return sum;
    }

    /**
     * 用指定数据初始化bytes
     *
     * @param len
     * @param value
     * @return
     */
    public static byte[] initBytes(int len, byte value) {
        byte[] data = new byte[len];
        for (int i = 0; i < len; i++) {
            data[i] = value;
        }
        return data;
    }

    /**
     * 将数据按指定长度输出 不足右补0x20
     *
     * @param bytes
     * @param len
     * @return
     */
    public static byte[] specifiedLengthBytes(byte[] bytes, int len) {
        if (bytes.length == len) {
            return bytes;
        }

        byte[] data = new byte[len];
        if (bytes.length > len) {
            System.arraycopy(bytes, 0, data, 0, len);
        } else {
            System.arraycopy(bytes, 0, data, 0, bytes.length);
            byte[] b = initBytes(len - bytes.length, (byte) 0x20);
            System.arraycopy(b, 0, data, bytes.length, b.length);
        }
        return data;
    }

    /**
     * 二进制数据转成字符串(默认编码)
     *
     * @param bys
     * @return
     */
    public static String bytesToString(byte[] bys) {
        return new String(bys);
    }

    public static int string2Int(String str) {
        return str == null ? 0 : Integer.parseInt(str);
    }

    /**
     * 把二进制数据转化为十六进制的字符串
     *
     * @param bys
     * @return
     * @author hz15051315
     * @date 2016年8月25日 下午2:01:45
     * @version
     */
    public static String binary2Hex(byte[] bys) {
        if (bys == null || bys.length < 1) {
            return null;
        }

        StringBuffer sb = new StringBuffer(100);

        for (byte b : bys) {
            if (b >= 16) {
                sb.append(Integer.toHexString(b));
            } else if (b >= 0) {
                sb.append("0" + Integer.toHexString(b));
            } else {
                sb.append(Integer.toHexString(b).substring(6, 8));
            }
        }

        return sb.toString();
    }

    /**
     * 把十六进制的字符串转化为二进制
     *
     * @param hex
     * @return
     * @author hz15051315
     * @date 2018年1月11日 上午11:04:20
     * @version
     */
    public static byte[] hex2Binary(String hex) {
        if (hex == null || hex.length() < 1) {
            return null;
        }

        if (hex.startsWith("0x") || hex.startsWith("0X")) {
            hex = hex.substring(2);
        }

        int len = hex.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("待转化的十六进制字符串长度应该为偶数");
        }

        byte[] bys = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            String tmp = hex.substring(i, i + 2);
            bys[i / 2] = (byte) Integer.parseInt(tmp, 16);
        }
        return bys;
    }

    /**
     * BCD转换字符串
     *
     * @param bytes
     * @return
     */
    public static String bcd2Str(byte[] bytes) {
        char temp[] = new char[bytes.length * 2], val;

        for (int i = 0; i < bytes.length; i++) {
            val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
            temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

            val = (char) (bytes[i] & 0x0f);
            temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
        }
        return new String(temp);
    }

    /**
     * BCD转int
     *
     * @param bytes
     * @return
     */
    public static int bcd2Int(byte[] bytes) {
        String value = bcd2Str(bytes);
        if (CommonUtils.isInt(value)) {
            return string2Int(value);
        }
        return 0;
    }


    /**
     * int转BCD
     *
     * @param wSrc
     * @return
     */
    public static byte[] int2Bcd(int wSrc) {
        byte[] b = new byte[2];
        b[0] = (byte) ((wSrc / 100) / 10 * 0x10 + (wSrc / 100) % 10);
        b[1] = (byte) ((wSrc % 100) / 10 * 0x10 + (wSrc % 100) % 10);
        return b;
    }

    public static void main(String[] args) {
        // byte[] buf = new byte[2];
        // buf[0] = 0x00;
        // buf[1] = 0x16;

        // int n = bytesToInt(buf);
        // System.out.println(n);

        System.out.println(shortToBytes((short) 0));
    }
}
